home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TESTSPAR / SPSCSI.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  16.1 KB  |  566 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; Nov-25-91 ml.    The ACSI DMA channel will be used in the Sparrow's
  5. ;        SCSI.  (Argh!)  So, code is modified to talk to the
  6. ;        5380 through wdl and wdc.  This means Sparrow's SCSI
  7. ;        inherited all the restrictions of ACSI, except for
  8. ;        the opcode of a command (now we get all 8 bits.)
  9. ;        This is a merge of acsi.s and scsi.s of v5.00.
  10. ;
  11. ; Dec-10-91 ml.    Don't need to have extra long timeout in _rcvspscsi()
  12. ;        and _wrtspscsi() because extended read and write are 
  13. ;        not supported due to the 8 bit counter in the DMAC.
  14. ;
  15. ; Jan-27-92 ml.    Try optimizing it.
  16. ;        *NOTE*  Do NOT use 'move.l's to select the SCSI 
  17. ;            registers and write data to them.  It is
  18. ;            because 680x0 writes the high word first.
  19. ;            So, writing a long word to WDCWDL means
  20. ;            writing the data before pointing to the
  21. ;            correct register.  In the ACSI code, the
  22. ;            move.l's are writing data to the previous
  23. ;            address, and setting up the address for
  24. ;            the next access.  It was confusing, and it
  25. ;            is not done here.
  26. ;
  27. ; Jan-28-92 ml.    In order for AHDI to work at IPL 7, Timer C is used
  28. ;        instead of hz_200 for timeout purposes.
  29. ;
  30. ; Feb-12-92 ml.    Modified to use the "flush" bit and the extended counter.
  31. ;-
  32.  
  33.  
  34. .include    "defs.h"
  35. .include    "sysvar.h"
  36. .include    "mfp.h"
  37. .include    "acsi.h"
  38. .include    "spscsi.h"
  39. .include    "macros.h"
  40. .include    "68030.s"
  41.  
  42. ;+
  43. ; Command length
  44. ;-
  45. NCMD    equ    6        ; length of short command (in bytes)
  46.  
  47.  
  48. .if    !DRIVER            ; not to be included in driver
  49. scxltmout:  dc.l    12001   ; SCSI extra long-timeout (>1 min)
  50. slwsclto:   dc.l    5000    ; SCSI long-timeout (>25 S) for stunit()
  51. slwscsto:   dc.l    42        ; SCSI short-timeout (>205 mS) for stunit()
  52. scltmout:   dc.l    201        ; SCSI long-timeout (>1000 ms)
  53. scstmout:   dc.l    101        ; SCSI short-timeout (>500 ms)
  54. rcaltm:        dc.l    801        ; time for drive recalibration (>4s)
  55. .else    ;!DRIVER
  56. .extern    scxltmout, slwsclto, slwscsto, scltmout, scstmout, rcaltm
  57. .endif    ;!DRIVER
  58.  
  59. .extern    setadma, setacnt, _hdone
  60. stat:        dc.w    0        ; status byte
  61. flush:        dc.b    0        ; flush flag
  62. .even
  63.  
  64. ;+
  65. ; smplspscsi() - send a simple SCSI command (ie. no DMA involved)
  66. ;
  67. ;    d0.w = physical unit number
  68. ;    d1.l = transfer length (in bytes)
  69. ;    d2.w = command length (NCMD or LCMD)
  70. ;    a0.l = buffer address
  71. ;-
  72.     .globl    _smplspscsi
  73. _smplspscsi:
  74.     st    flock
  75.     andi.w    #7,d0            ; mask off the flags to get unit num
  76.     bsr    sblkspscsi        ; send command block
  77.     tst.w    d0            ; successful?
  78.     bmi.s    .0            ; if not, go clean up
  79.     bsr    w4spstat        ; else wait for status
  80. .0:    RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  81.     bra    _hdone            ; go clean up
  82.  
  83.  
  84.  
  85. ;+
  86. ; rcvspscsi() - send a SCSI command which receives data back.
  87. ;
  88. ; Passed:
  89. ;    d0.w = physical unit number
  90. ;    d1.l = transfer length (in bytes)
  91. ;    d2.w = command length (NCMD or LCMD)
  92. ;    a0.l = buffer address
  93. ;-
  94.     .extern    _cachexst
  95.     .globl    _rcvspscsi
  96. _rcvspscsi:
  97.     st    flock            ; lock FIFO
  98.     andi.w    #7,d0            ; mask off the flags to get unit num
  99.     movem.l    d1-d2/a0,-(sp)        ; save buffer address and cmd length
  100.     bsr    sblkspscsi        ; send command block
  101.     movem.l    (sp)+,d1-d2/a0        ; restore buffer address and cmd len
  102.     tst.w    d0            ; successful?
  103.     bmi    rspend            ; if not successful, return
  104.  
  105. ;+
  106. ; Feb-13-1992    Check whether FIFO needs to be flushed.
  107.     sf    flush            ; assume no need to flush
  108.     move.l    d1,d0            ; d0 = transfer length
  109.     andi.l    #$0f,d0            ; multiple of 16?
  110.     beq.s    rdma0            ; if so, no need to flush
  111.     st    flush            ; else, set flush flag
  112. ;-
  113.  
  114. rdma0:    WSCSI    #0,#SPSCSIICR        ; deassert the data bus
  115.     WSCSI    #1,#SPSCSITCR        ; set data in phase
  116.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  117.  
  118. .if    SPSCDMA                ; Set up the DMAC for data transfer
  119. ;    cmpi.l    #512,d1            ; transferring >= 512 bytes?
  120. ;    bcs    rpio            ; if not, do programmed IO
  121. ;                    ; else set up DMA chip for DMA
  122.  
  123.     WSCSI    #2,#SPSCSIMR        ; enable DMA mode
  124.      movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  125.     bsr    setadma            ; set DMA pointer
  126.     move.w    #$190,XWDL(a1)    ;WDL    ; toggle DMA chip for "receive"
  127.     RSTDELAY            ; delay
  128.     move.w    #$090,XWDL(a1)    ;WDL
  129.     RSTDELAY            ; delay
  130.     bsr    setacnt
  131.  
  132. rdma1:    btst.b    #STA,WDSR        ; wait till it's safe to access
  133.     bne.s    rdma1            ;  the DMA channel
  134.  
  135. ;    TMOUT    #2,d0            ; delay before using DMA channel
  136. ;    CNTALL    d0
  137.  
  138.     WSCSI    #0,#SPSCSIDIR        ; start the DMA receive
  139.     move.w    #0,WDL
  140.  
  141. ;+
  142. ; Dec-10-1991    ml.    Don't need to have extra long timeout because
  143. ;            extended read and write are not supported due
  144. ;            to the 8 bit counter in the DMAC.
  145. ;
  146. ; Feb-13-1992    ml.    Put code back in because DMAC has been modified
  147. ;            to have a 14-bit counter.
  148.     moveq    #0,d0            ; assume no extra timeout
  149.     cmpi.w    #NCMD,d2        ; is this a long command?
  150.     beq.s    rdma2            ; if not, just go on
  151.     move.l    scxltmout,d0        ; set up an extra long timeout
  152. ;-
  153.  
  154. rdma2:    bsr    w4spint            ; wait for interrupts
  155.     tst.w    d0            ; successful?
  156.     bne.s    rspend            ; if error, returns
  157.  
  158. ;+
  159. ; Feb-13-1992    ml.    Added code to use the flush bit on the DMAC.
  160. ;            Now, we can do DMA without sending a command
  161. ;            multiple times, to write everything from the 
  162. ;            FIFO to memory, for transfers of non-multiple
  163. ;            of 16 bytes.  Using this flush function requires
  164. ;            the buffer provided for the command to be as big 
  165. ;            as the closest multiple of 16 to receive all data.
  166. ;            
  167.     tst.b    flush            ; need to flush FIFO?
  168.     beq.s    rdma3            ; if not, proceed    
  169.     move.w    #$0020,WDL        ; else flush (Whoosh!)
  170. ;-
  171. rdma3:    tst.b    _cachexst        ; is there a cache to flush?
  172.     beq.s    rstat            ; if not, go get status
  173.     move    sr,-(sp)        ; go to IPL 7
  174.     ori    #$700,sr        ; no interrupts right now kudasai
  175.     movecacrd0            ; d0 = (cache control register)
  176.     ori.w    #$808,d0        ; dump both the D and I cache
  177.     moved0cacr            ; update cache control register
  178.     move    (sp)+,sr        ; restore interrupt state
  179.     bra.s    rstat            ; go read status 
  180. .endif    ;SPSCDMA
  181.  
  182. rpio:    movea.l    a0,a1            ; a1 -> buffer to read into
  183. rnxtb:    bsr    w4spdreq        ; wait for REQ for data to come
  184.     bmi.s    rspend            ; if timed out, returns
  185.     RSCSI    #SPSCSIDSR,d0        ; still in data in phase?
  186.     btst    #3,d0            
  187.     beq    rstat            ; if not, go get status
  188.     RSCSI    #bSPSCSI,d0        ; else read the next data byte
  189.     move.b    d0,(a1)+    
  190.     bsr    dospack
  191.     bra.s    rnxtb            ; do next byte
  192. rstat:    bsr    w4spstat        ; go get status byte
  193. rspend:    RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  194.     bra    _hdone            ; go clean up
  195.  
  196.  
  197.  
  198. ;+
  199. ; wrtspscsi() - send a SCSI command which will write data to the target
  200. ;
  201. ; Passed:
  202. ;    d0.w = physical unit number
  203. ;    d1.l = transfer length (in bytes)
  204. ;    d2.w = command length (NCMD or LCMD)
  205. ;    a0.l = buffer address
  206. ;
  207. ; Comments: 
  208. ; 12/04/89 ml
  209. ;    Bus error occurs when doing a write to the disk that ends at top
  210. ; of memory.  The DMA counter is decremented when the bytes are written 
  211. ; from the ping pong buffers to the device, not when bytes are grapped 
  212. ; from RAM to the ping pong buffers.  Well, AFTER the last 8 bytes are 
  213. ; read into the ping pong buffers and BEFORE they are written to the 
  214. ; device, the chip will attempt to read the NEXT 8 bytes into the ping 
  215. ; pong buffers which results in a bus error because it will be reading 
  216. ; pass top of memory.  To get around this HARDWARE BUG, the code will 
  217. ; ALWAYS handshake the last 8 bytes over instead of DMAing them.
  218. ;
  219. ; 01/23/90 ml
  220. ;    A. Pratt said he's willing to move the screen down and sacrifice
  221. ; 16 bytes of memory.  So, code added on 12/04/89 is commented out.
  222. ;-
  223.     .globl    _wrtspscsi
  224. _wrtspscsi:
  225.     st    flock            ; lock FIFO
  226.     andi.w    #7,d0            ; mask off the flags to get unit num
  227.  
  228.     movem.l    d1-d2/a0,-(sp)        ; save beginning buffer address
  229.     bsr    sblkspscsi        ; send command block
  230.     movem.l    (sp)+,d1-d2/a0        ; a0 = where DMA ends
  231.     tst.w    d0            ; successful?
  232.     bmi    wspend            ; if not, go clean up
  233.  
  234.     WSCSI    #0,#SPSCSITCR        ; set data out phase
  235.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  236.  
  237. .if    SPSCDMA
  238.                     ; Set up the DMAC for data transfer
  239.     cmpi.l    #512,d1            ; transferring >= 512 bytes?
  240.     bcs.s    wpio            ; if not, do programmed IO
  241.                     ; else do DMA
  242.     WSCSI    #2,#SPSCSIMR        ; enable DMA mode
  243.  
  244.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  245.  
  246.     bsr    setadma            ; set DMA pointer
  247.     move.w    #$90,XWDL(a1)    ;WDL    ; toggle DMA chip for "send"
  248.     RSTDELAY            ; delay 
  249.     move.w    #$190,XWDL(a1)    ;WDL
  250.     RSTDELAY            ; delay
  251.     bsr    setacnt            ; set DMA count
  252.  
  253. wdma0:    btst.b    #STA,WDSR        ; wait till it's safe to access
  254.     bne.s    wdma0            ;  the DMA channel
  255.  
  256. ;    TMOUT    #2,d0            ; delay before using DMA channel
  257. ;    CNTALL    d0
  258.  
  259.     WSCSI    #0,#($100|SPSCSIDS)    ; start the DMA send
  260.     move.w    #$100,WDL
  261.  
  262. ;+
  263. ; Dec-10-1991    ml.    Don't need to have extra long timeout because
  264. ;            extended read and write are not supported due
  265. ;            to the 8 bit counter in the DMAC.
  266. ;
  267.     moveq    #0,d0            ; assume no extra timeout
  268.     cmpi.w    #NCMD,d2        ; is this a long command?
  269.     beq.s    wdma1            ; if not, just go on
  270.     move.l    scxltmout,d0        ; set up an extra long timeout
  271. ;-
  272.  
  273. wdma1:    bsr    w4spint            ; wait for interrupts
  274.     tst.w    d0
  275.     beq.s    wstat            ; if ok, wait for status byte
  276.     bra.s    wspend            ; else return
  277. .endif    ;SPSCDMA
  278.                     ; hand shake data over the bus
  279. wpio:    movea.l    a0,a1            ; a1 -> buffer to write from
  280. wnxtb:    bsr    w4spdreq        ; wait for REQ for data to come
  281.     bmi.s    wspend            ; if timed out, returns
  282.     RSCSI    #SPSCSIDSR,d0
  283.     btst    #3,d0            ; still in data out phase?
  284.     beq.s    wstat            ; if not, go get status
  285.     moveq    #0,d0
  286.     move.b    (a1)+,d0        ; write the next data byte
  287.     WSCSI    d0,#bSPSCSI
  288.     bsr    dospack
  289.     bra.s    wnxtb            ; do next byte
  290. wstat:    bsr    w4spstat        ; get status byte
  291. wspend:    RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  292.     bra    _hdone            ; go clean up
  293.  
  294.  
  295.  
  296. ;+
  297. ; sblkspscsi() - set DMA pointer and count and send command block
  298. ;
  299. ; Passed:
  300. ;    d0.w = physical unit number
  301. ;    d1.l = transfer length (in bytes)
  302. ;    d2.w = command length (NCMD or LCMD)
  303. ;    a0.l = buffer address
  304. ;
  305. ; Returns:
  306. ;    d0.l =  0 if successful
  307. ;    d0.l = -1 if timeout
  308. ;-
  309.     .extern    _cmdblk
  310. sblkspscsi:
  311.     movem.l    d1-d2/a0,-(sp)        ; preserve d1, d2 and a0
  312.     move.w    d0,-(sp)        ; physical unit #
  313.     bsr    selspscsi        ; select the unit
  314.     addq.l    #2,sp            ; clean up stack
  315.     movem.l    (sp)+,d1-d2/a0        ; restore d1, d2 and a0
  316.     tst.w    d0            ; selection successful?
  317.     bmi.s    sbspend            ; if timed out, return
  318.                     ; else proceed
  319.     WSCSI    #2,#SPSCSITCR        ; assert C/D
  320.     WSCSI    #1,#SPSCSIICR        ; assert data bus
  321.  
  322.     lea    _cmdblk,a1        ; a1 -> command block
  323.     subq.w    #1,d2            ; dbra likes one less
  324. sbs0:    bsr    w4spreq            ; wait for REQ to come
  325.     bmi.s    sbspend            ; if timed out, returns
  326.     move.b    (a1)+,d0        ; d0.b = byte to be sent
  327.     WSCSI    d0,#SPSCSIDB        ; write a byte out to data bus
  328.     bsr    dospack            ; assert ACK
  329.     dbra    d2,sbs0            ; until whole command block is sent
  330.     moveq    #0,d0            ; all operations successful
  331. sbspend: rts                ; heading home
  332.  
  333.  
  334. ;+
  335. ; BOOLEAN selspscsi(SCSIUnit) 
  336. ; WORD SCSIUnit;
  337. ;-
  338. selspscsi:
  339.     TMOUT    scstmout,d1        ; set up a short timeout
  340.     move.w    #SPSCSICR,WDL
  341. .0:    move.w    WDC,d0
  342.     btst    #6,d0            ; STILL busy from last time?
  343.     beq.s    .1            ; if not, it's available
  344.     CNTDN1    d1,.0            ; else if not timed-out, wait longer
  345.     bra    .3            ; else, return error
  346.  
  347. .1:    WSCSI    #0,#SPSCSITCR        ; data out phase
  348.     WSCSI    #0,#SPSCSIISR        ; no interrupt from selection
  349.     WSCSI    #$0c,#SPSCSIICR        ; assert BSY and SEL
  350. ; set dest SCSI IDs
  351.     clr.w    d0
  352.     move.w    4(sp),d1        ; get the SCSI unit desired
  353.     bset    d1,d0            ; set the appropriate bit
  354.     WSCSI    d0,#SPSCSIODR        ; (real code would set ours too)
  355.  
  356. ;    WSCSI    #$0d,#SPSCSIICR        ; assert BUSY, SEL and data bus
  357.     WSCSI    #$05,#SPSCSIICR        ; assert SEL and data bus
  358.     RSCSI    #SPSCSIMR,d0        ; read Mode Register
  359.     andi.b    #$fe,d0            ; clear arbitrate bit
  360.     move.w    d0,WDC
  361.     RSCSI    #SPSCSIICR,d0        ; read Initiator Command Register
  362.     andi.b    #$f7,d0            ; clear BUSY
  363.     move.w    d0,WDC
  364.     nop                ; 2 deskew delays
  365.     nop
  366.  
  367.     TMOUT    scstmout,d1        ; set up timeout counter
  368.     move.w    #SPSCSICR,WDL
  369. .2:    move.w    WDC,d0            ; wait for bus to be busy
  370.     btst    #6,d0
  371.     bne.s    .4
  372.  
  373.     CNTDN1    d1,.2            ; if not timed-out, wait some more
  374.  
  375. .3:    moveq    #-1,d0            ; time out
  376.     bra.s    .5
  377.     
  378. .4:    clr.w    d0            ; selection successful
  379. .5:    WSCSI    #0,#SPSCSIICR        ; clear SEL and data bus assertion
  380.     rts
  381.  
  382.  
  383. ;+
  384. ; VOID resetspscsi();
  385. ;
  386. ; Feb-14-1992    ml.    Added code to reset DMAC before talking through
  387. ;            it to reset the SCSI bus.  To protect DMAC from
  388. ;            locking up, check if it's safe to access it
  389. ;            before doing any of the above.
  390. ;-
  391.     .globl    resetspscsi
  392.     .extern    setscstmout
  393.     .extern    setscltmout
  394. resetspscsi:
  395. rst0:    btst.b    #STA,WDSR    ; wait till it's safe to access
  396.     bne.s    rst0        ;  the DMA channel
  397.  
  398.     move.w    #$190,WDL    ; reset DMA chip
  399.     RSTDELAY        ; delay
  400.     move.w    #$090,WDL
  401.     RSTDELAY
  402.                 ; reset SCSI bus
  403.     WSCSI    #$80,#SPSCSIICR    ; assert RST
  404. ;    TMOUT    scstmout,d1    ; wait (at least) 250 ms
  405. ;    CNTALL    d1
  406.     bsr    setscstmout    ; wait (at least) 250 ms
  407. .0:    cmp.l    (a0),d1
  408.     bhi.s    .0
  409. ;    move.w    #0,WDC
  410.     WSCSI    #0,#SPSCSIICR    ; clear RST
  411. ;    TMOUT    scltmout,d1    ; wait (at least) 1000 ms
  412. ;    CNTALL    d1
  413.     bsr    setscltmout    ; wait (at least) 1000 ms
  414. .1:    cmp.l    (a0),d1
  415.     bhi.s    .1
  416.     rts
  417.  
  418.  
  419. ;+
  420. ; w4spint - wait for interrupts from 5380 or DMAC during DMA tranfers
  421. ;
  422. ; Returns:
  423. ;    d0.l = returned status or timeout error
  424. ;
  425. ; Comments:
  426. ;    When 5380 is interrupted, it indicates a change of data to
  427. ; status phase (i.e., DMA is done), or ...
  428. ;    When DMAC is interrupted, it indicates either DMA count is
  429. ; zero, or there is an internal bus error.
  430. ;-
  431. w4spint:
  432.     TMOUT    rcaltm,d1        ; set timeout (incl. recalibration)
  433.     add.l    d0,d1
  434. .0:    btst    #5,GPIP            ; interrupt?
  435.     beq.s    .1            ; active LOW
  436.     CNTDN1    d1,.0            ; if there's more time, keep waiting
  437.                     ; else timed-out
  438.     bsr    resetspscsi        ; reset the SCSI bus
  439.     moveq    #-1,d0            ; return timeout
  440.     bra.s    w4spiend
  441.  
  442. .1:    moveq    #0,d0            ; DMA is successful
  443.     RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  444.     WSCSI    #0,#SPSCSIMR        ; disable DMA mode
  445.     WSCSI    #0,#SPSCSIICR        ; make sure data bus is not asserted
  446. w4spiend:
  447.     rts
  448.  
  449.  
  450. ;+
  451. ; w4spstat - wait for status byte and message byte.
  452. ;
  453. ; Returns:
  454. ;    d0.l = returned status or timeout error
  455. ;-
  456. w4spstat:
  457.     WSCSI    #3,#SPSCSITCR        ; status in phase
  458.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  459.  
  460.     bsr    w4spreq            ; wait for status byte
  461.     bmi.s    w4spend            ; if timed-out, returns
  462. gspstat:
  463.     RSCSI    #SPSCSIDB,d0        ; get the status byte
  464.     andi.w    #$ff,d0
  465.     move.w    d0,stat            ; save the status byte
  466.     bsr    dospack            ; signal that status byte is here
  467.  
  468. .1:    bsr    w4spreq            ; wait for message byte
  469.     bmi.s    w4spend            ; if timed-out, returns
  470.  
  471.     RSCSI    #SPSCSIDB,d0        ; get and ignore message byte
  472.     bsr    dospack            ; signal that message byte is here
  473.     move.w    stat,d0            ; recall the status byte
  474. w4spend:
  475.     rts                ; return
  476.  
  477.  
  478. ;+
  479. ; w4spdreq() - wait for REQ to come during hand shake of data bytes
  480. ; w4spreq() - wait for REQ to come during hand shake of non-data bytes
  481. ;
  482. ; Returns:
  483. ;     0 - if successful
  484. ;    -1 - times out
  485. ;-
  486. w4spdreq:
  487.     TMOUT    rcaltm,d1        ; add time for recalibration
  488.     bra.s    w4req0
  489. w4spreq:
  490.     TMOUT    scstmout,d1        ; set up timeout counter
  491. w4req0:    move.w    #SPSCSICR,WDL
  492. .1:    move.w    WDC,d0            ; read Control Register
  493.     btst    #5,d0            ; waiting for REQ to come
  494.     bne.s    .2            ; if REQ comes, done
  495.     CNTDN1    d1,.1            ; if there is more time, keep waiting
  496.     moveq    #-1,d0            ; else, returns timed out
  497.     bra.s    w4sprend
  498. .2:    moveq    #0,d0            ; returns successful
  499. w4sprend:
  500.     rts
  501.  
  502.  
  503. ;+
  504. ; dospack() - assert ACK
  505. ;
  506. ; Returns:
  507. ;     0 - always successful
  508. ;-
  509. dospack:    
  510.     RSCSI    #SPSCSIICR,d0        ; read Initiator Command Register
  511.     ori.b    #$11,d0            ; assert ACK (and data bus)
  512.     move.w    d0,WDC
  513.     andi.b    #$ef,d0            ; clear ACK
  514.     move.w    d0,WDC
  515.     moveq    #0,d0
  516.     rts
  517.  
  518.  
  519. .if    !DRIVER                ; not to be included in driver
  520.  
  521. ;+
  522. ; fmtspscsi() - format a SCSI unit
  523. ;
  524. ;    d0.w = physical unit number
  525. ;    d1.l = transfer length (in bytes)
  526. ;    d2.w = command length (NCMD or LCMD)
  527. ;    a0.l = buffer address
  528. ;-
  529.     .globl    _fmtspscsi
  530. _fmtspscsi:
  531.     st    flock            ; lock FIFO
  532.     andi.w    #7,d0            ; mask off the flags to get unit num
  533.     bsr    sblkspscsi        ; send command block
  534.     bpl.s    .0            ; if successful, wait for status byte
  535.     rts                ; else return
  536. .0:    WSCSI    #3,#SPSCSITCR        ; status in phase
  537.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  538. .1:    RSCSI    #SPSCSICR,d0        ; read Control Register
  539.     btst    #5,d0            ; wait forever for REQ to come
  540.  
  541.  
  542. .if    DEBUG
  543.  
  544.     bne.s    .3            ; For debugging purpose - 
  545.     move.l    #_hz_200,a0        ;    add a delay in this "tight" 
  546.     moveq    #2,d1            ;    loop to slow down SCSI chip 
  547.     add.l    (a0),d1            ;    accessing.
  548. .2:    cmp.l    (a0),d1
  549.     bhi.s    .2
  550.     bra.s    .1
  551.  
  552. .else    ;DEBUG
  553.  
  554.     beq.s    .1
  555.  
  556. .endif    ;DEBUG
  557.  
  558. .3:    bsr    gspstat            ; when REQ comes, get status byte
  559.     RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  560.     bra    _hdone            ; go clean up
  561.  
  562. .endif    ;!DRIVER
  563.  
  564.  
  565.  
  566.